package torque.generated;

import org.apache.torque.TorqueException;
import org.apache.torque.om.Persistent;
import org.apache.torque.util.Criteria;
import java.util.*;

/**
 * 
 * Un {@link Trolldanspartie} est une incarnation d'un {@link Troll} dans une {@link Partie}. Il est lié a ce dernier pour les statistiques. Il possèdes des PV et PA ainsi que les positions X et Y.
 */
public class Trolldanspartie extends torque.generated.BaseTrolldanspartie
		implements Persistent {
	/** Serial version */
	private static final long serialVersionUID = 1317634214273L;
	/** Valeur fixe correspondant au maximum de PA pour un {@link Trolldanspartie}
	 * 
	 */
	private static int maxPa = 6;
	/** Cout pour ramasser un objet
	 * 
	 */
	private static int prixPaRamasser = 1;
	/**
	 * Cout d'un déplacement en PA
	 */
	private static int prixPaDeplacer = 2;
	/**
	 * Cout supplémentaire si il y a un ou x {@link Trolldanspartie} à la position de destination
	 */
	private static int prixPaRamasserMalusTroll = 2;

	/**
	 * Cout pour attaquer un Troll
	 */
	private static int prixPaAttaquer = 3;
	
	
	/**
	 * Cout pour équiper/utiliser un objet en PA
	 */
	private static int prixPaEquiper = 1;
	/** Est il mort ?
	 * @return <code>true</code> si PV>0 Sinon <code>false</code>
	 * 
	 */
	public boolean isdead() {
		if (this.getPv() == 0)
			return true;
		return false;
	}

	/** Retourne la valeur des jets d'attaques pour un troll
	 * @return {@link Integer} Valeur
	 */
	public int getOneAttaque() { // Renvois l'attaque pour 1 attaque
		try {

			int d3 = (int) Math.ceil(Math.random() * 3) + 1;
			int value = (int) this.getTroll().getAttaque();
			int b = 0;
			int r = 0;
			String nt = this.getNomtroll();
			Criteria crit = new Criteria();
			crit.add(ObjetdanstrolldanspartiePeer.NOMTROLL, this.getNomtroll());
			crit.add(ObjetdanstrolldanspartiePeer.IDPARTIE, this.getIdpartie());
			crit.add(ObjetdanstrolldanspartiePeer.EQUIPE, "true");
			List<Objetdanstrolldanspartie> odtdps = ObjetdanstrolldanspartiePeer
					.doSelect(crit);
			for (Objetdanstrolldanspartie odtdp : odtdps) {
				b += odtdp.getObjetdanspartie().getObjet().getBonusattaque();
			}
			r = (value + b) * d3;
			System.out.println("<Tir de D3> " + nt + " [Attaque] : " + value
					+ "(+" + b + ")*" + d3 + " = " + r);
			return r;
		} catch (TorqueException e) {

			e.printStackTrace();
		}
		return 0;
	}

	/** Retourne la valeur d'un jet de dégat pour un troll
	 * @return {@link Integer} Valeur
	 */
	public int getOneDegat() { // Renvois les degats pour 1 attaque
		try {

			int d3 = (int) Math.ceil(Math.random() * 3) + 1;
			int value = (int) this.getTroll().getAttaque();
			int b = 0;
			int r = 0;
			String nt = this.getNomtroll();
			Criteria crit = new Criteria();
			crit.add(ObjetdanstrolldanspartiePeer.NOMTROLL, this.getNomtroll());
			crit.add(ObjetdanstrolldanspartiePeer.IDPARTIE, this.getIdpartie());
			crit.add(ObjetdanstrolldanspartiePeer.EQUIPE, "true");
			List<Objetdanstrolldanspartie> odtdps = ObjetdanstrolldanspartiePeer
					.doSelect(crit);
			for (Objetdanstrolldanspartie odtdp : odtdps) {
				b += odtdp.getObjetdanspartie().getObjet().getBonusdegat();
			}
			r = (value + b) * d3;
			System.out.println("<Tir de D3> " + nt + " [Degat] : " + value + "(+"
					+ b + ")*" + d3 + " = " + r);
			return r;
		} catch (TorqueException e) {

			e.printStackTrace();
		}
		return 0;
	}

	/** Retourne la valeur d'un jet d'Esquive pour un troll
	 * @return {@link Integer} Valeur
	 */
	public int getOneEsquive() { // Renvois l'attaque pour 1 attaque
		try {

			int d3 = (int) Math.ceil(Math.random() * 3) + 1;
			int value = (int) this.getTroll().getEsquive();
			int b = 0;
			int r = 0;
			String nt = this.getNomtroll();
			Criteria crit = new Criteria();
			crit.add(ObjetdanstrolldanspartiePeer.NOMTROLL, this.getNomtroll());
			crit.add(ObjetdanstrolldanspartiePeer.IDPARTIE, this.getIdpartie());
			crit.add(ObjetdanstrolldanspartiePeer.EQUIPE, "true");
			List<Objetdanstrolldanspartie> odtdps = ObjetdanstrolldanspartiePeer
					.doSelect(crit);
			for (Objetdanstrolldanspartie odtdp : odtdps) {
				b += odtdp.getObjetdanspartie().getObjet().getBonusesquive();
			}
			r = (value + b) * d3;
			System.out.println("<Tir de D3> " + nt + " [Esquive] : " + value
					+ "(+" + b + ")*" + d3 + " = " + r);
			return r;
		} catch (TorqueException e) {

			e.printStackTrace();
		}
		return 0;
	}

	/** Reset les PV du {@link Trolldanspartie} en fonction de ses statistiques de vie.
	 * @return {@link Integer} PV
	 */
	public int resetPV() {
		try {
			this.setPv(this.getTroll().getVie() * 10);

			return this.getTroll().getVie() * 10;
		} catch (TorqueException e) {

			e.printStackTrace();
		}
		return 0;
	}

	/** Reset les PA du Trolldanspartie.
	 * @return {@link Integer} des PA une fois Reset (plus les bonus des objets)
	 */
	public int resetPA() {
		try {
			Criteria crit = new Criteria();
			crit.add(ObjetdanstrolldanspartiePeer.NOMTROLL, this.getNomtroll());
			crit.add(ObjetdanstrolldanspartiePeer.IDPARTIE, this.getIdpartie());
			crit.add(ObjetdanstrolldanspartiePeer.EQUIPE, "true");
			List<Objetdanstrolldanspartie> objs = ObjetdanstrolldanspartiePeer
					.doSelect(crit);
			int bonusPa = 0;

			for (Objetdanstrolldanspartie obj : objs) {
				if(obj.getEquipe())
					bonusPa += obj.getObjetdanspartie().getObjet().getBonuspa();
			}

			this.setPa(maxPa + bonusPa);

			return this.getTroll().getVie() * 10;
		} catch (TorqueException e) {

			e.printStackTrace();
		}
		return 0;
	}

	/** Retourne l'inventaire d'un Troll
	 * @return {@link List}<{@link Objetdanstrolldanspartie}> listes des objets de l'inventaire du Troll
	 */
	public java.util.List<Objetdanstrolldanspartie> getObjets() {
		Criteria crit = new Criteria();
		crit.add(ObjetdanstrolldanspartiePeer.NOMTROLL, this.getNomtroll());
		crit.add(ObjetdanstrolldanspartiePeer.IDPARTIE, this.getIdpartie());
		try {
			return ObjetdanstrolldanspartiePeer.doSelect(crit);
		} catch (TorqueException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * Fonction qui remet les PA a maxPa, et déclenche la fonction nouveauTour() pour les {@link Objetdanstrolldanspartie} liés au {@link Trolldanspartie}
	 */
	public void nouveauTour() {
		try {
			List<Objetdanstrolldanspartie> objs = this.getObjets();
			for (Objetdanstrolldanspartie obj : objs) {
				obj.nouveauTour();
			}
			this.resetPA();

			this.save();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("Erreur a la mise a jour des trolls");
			e.printStackTrace();
		}

	}

	/**
	 * Ramasse l'objet sur la même position que le Troll
	 * 
	 */
	public void ramasser() {// TODO
		try {
			int pa = this.getPa();
			if (pa < prixPaRamasser) {
				System.out.println("Il vous manque " + (prixPaRamasser - pa)
						+ "PA pour effectuer cette action");
				return;
			}
			pa -= prixPaRamasser;
			int chance = (int) Math.floor(Math.random() * 100);
			if (chance > 80) {
				System.out.println("L'action a échoué !");
				return;
			}
			Partie partie=PartiePeer.retrieveByPK(this.getIdpartie());
			Objetdanspartie obj = partie.getObjet(this.getX(),
					this.getY());
			this.setPa(pa);
			if (obj != null) {
				Objetdanstrolldanspartie odtdp = new Objetdanstrolldanspartie();
				odtdp.setTrolldanspartie(this);
				odtdp.setObjetdanspartie(obj);
				odtdp.setTour(obj.getObjet().getDuree());
				odtdp.setEquipe(false);
				odtdp.save();
				System.out.println(":) "+this.getNomtroll()+" a ramassé ["+odtdp.getObjetdanspartie().getNomobjet()+"]");
			}
			this.save();
			obj.save();
			this.getObjetdanstrolldansparties(new Criteria());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Permet de déplacer le troll
	 * 
	 * @param relx
	 *            -1 pour aller a gauche, +1 pour aller a droite
	 * @param rely
	 *            idem pour haut / bas
	 */
	public boolean seDeplacer(int relx, int rely) {// TODO
		try {
			int prix = prixPaDeplacer;
			if (!TrolldanspartiePeer.getTrolls(this.getX() + relx,
					this.getY() + rely, this.getIdpartie()).isEmpty())
			prix += prixPaRamasserMalusTroll;

			int pa = this.getPa();
			if (pa < prix) {
				System.out.println("Il vous manque " + (prix - pa)
						+ "PA pour effectuer cette action");
				return false;
			}
			pa -= prix;
			int chance = (int) Math.floor(Math.random() * 100);
			if (chance > 80) {
				System.out.println("L'action a échoué !");
				return false;
			}
			this.setPa(pa);
			this.setX(this.getX() + relx);
			this.setY(this.getY() + rely);
			this.save();
			System.out.println(":) "+this.getNomtroll()+" se déplace en ("+this.getX()+","+this.getY()+")");
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	
	/** Suppression en cascade du {@link Trolldanspartie} et de ses {@link Objetdanstrolldanspartie}
	 * @throws TorqueException Exceptions générées par la suppression
	 */
	public void delete() throws TorqueException{
		List<Objetdanstrolldanspartie> os = this.getObjetdanstrolldansparties(new Criteria());
		for(Objetdanstrolldanspartie o : os){
			ObjetdanstrolldanspartiePeer.doDelete(o);
		}
		TrolldanspartiePeer.doDelete(this);
	}

	/** Attaque le {@link Trolldanspartie} trolla <p>Cette fonction ne vérifie pas la position des Trolls, permettant des attaques a distances.</p>
	 * @param trolla {@link Trolldanspartie} a attaquer
	 * @return True si l'attaque a réussie ! False sinon;
	 * 
	 */
	public boolean Attaquer(Trolldanspartie trolla){
		int prix=prixPaAttaquer;
		int pa = this.getPa();
		if (pa < prix) {
			System.out.println("Il vous manque " + (prix - pa)
					+ "PA pour effectuer cette action");
			return false;
		}
		int chance = (int) Math.floor(Math.random() * 100);
		if (chance > 80) {
			System.out.println("L'action a échoué !");
			return false;
		}
		int trollcAttaque = this.getOneAttaque();
		int trollaEsquive = trolla.getOneEsquive();
		if(trollaEsquive<trollcAttaque){
			int trollcDegat = this.getOneDegat();
			int trollaVie = trolla.getPv();
			trolla.setPv(trollaVie - trollcDegat);
			System.out.println(":) "+this.getNomtroll()+" inflige "+ trollcDegat +" dégats à :) "+trolla.getNomtroll()+" !");
			System.out.println(":) "+trolla.getNomtroll()+" a "+trolla.getPv()+"PV !");
			if(trolla.isdead()){
				System.out.println("C'étais le coup de grace ! :) "+trolla.getNomtroll()+" est mort.");
			}
			return true;
		} else{
			System.out.println(":) "+trolla.getNomtroll()+" a esquivé l'attaque !");
			return false;
		}
		
	}
	
	public boolean equiper(Objetdanstrolldanspartie obj){
		try{
			
			
			int prix=prixPaEquiper;
			int pa = this.getPa();
			if (pa < prix) {
				System.out.println("Il vous manque " + (prix - pa)
						+ "PA pour effectuer cette action");
				return false;
			}
			int chance = (int) Math.floor(Math.random() * 100);
			if (chance > 80) {
				System.out.println("L'action a échoué !");
				return false;
			}
			Criteria crit = new Criteria();
			/*crit.add(ObjetdanspartiePeer.XDEPART, obj.getXdepart());
			crit.and(ObjetdanspartiePeer.YDEPART, obj.getYdepart());
			crit.and(ObjetdanspartiePeer.IDPARTIE, obj.getIdpartie());
			crit.and(ObjetPeer.NOMOBJET, ObjetdanspartiePeer.NOMOBJET);
			List<Objet> os = ObjetPeer.doSelect(crit);
			if(os.isEmpty()) throw new Exception("Erreur dans la récupération de l'objet");
			Objet o = os.get(0);*/
			System.out.println(obj.toString());
			Objetdanspartie o = obj.getObjetdanspartie();
			System.out.printf(o.toString());
			crit = new Criteria();
			crit.add(ObjetdanstrolldanspartiePeer.NOMTROLL,this.getNomtroll());
			crit.add(ObjetdanstrolldanspartiePeer.EQUIPE,"true");
			crit.add(ObjetdanstrolldanspartiePeer.XDEPART, ObjetdanspartiePeer.XDEPART);
			crit.add(ObjetdanstrolldanspartiePeer.YDEPART, ObjetdanspartiePeer.YDEPART);
			crit.add(ObjetdanstrolldanspartiePeer.IDPARTIE, ObjetdanspartiePeer.IDPARTIE);
			crit.add(ObjetdanstrolldanspartiePeer.IDPARTIE, this.getIdpartie());
			crit.add(ObjetdanspartiePeer.NOMOBJET, ObjetPeer.NOMOBJET);
			//crit.add(ObjetPeer.TYPE, o.getType());
			
			List<Objetdanstrolldanspartie> objdt2 = ObjetdanspartiePeer.doSelect(crit);
			if(!objdt2.isEmpty()){
				objdt2.get(0).setEquipe(false);
				objdt2.get(0).save();
				System.out.println("["+objdt2.get(0).getObjetdanspartie().getNomobjet()+"] n'est plus équipé");
			}
			obj.setEquipe(true);
			obj.save();
			System.out.println("["+obj.getObjetdanspartie().getNomobjet()+"] est plus équipé");
		}catch(Exception e){
			e.printStackTrace();
		}
		return false;
	}
}
